package com.lss233.recipeguide.listener;

import com.lss233.recipeguide.RecipeData;
import com.lss233.recipeguide.RecipeGuide;
import com.lss233.recipeguide.Storage;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryOpenEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.nio.DoubleBuffer;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author Lss233
 */
public class GuiMenuListener implements Listener {
    /*
    = = = = = = = = =       = : Frame
    = * * * = = = = =       * : Recipe item
    = * * * = = = X =       X : Result item
    = * * * = = = = =       - : Operation item
    = = = = = = = = =
    = - = - = = = = =
*/
    private final byte[] frame = new byte[]{
            0, 0, 0, 0, 0, 0, 0, 0, 0,
            0, 1, 1, 1, 0, 0, 0, 0, 0,
            0, 1, 1, 1, 0, 0, 0, 4, 0,
            0, 1, 1, 1, 0, 0, 0, 0, 0,
            0, 0, 0, 0, 0, 0, 0, 0, 0,
    };

    public static Map<Player, Inventory> getOpeningMap() {
        return openingMap;
    }

    private static Map<Player, Inventory> openingMap = new HashMap<>();

    @EventHandler
    public void onClose(InventoryCloseEvent event) {
        if (openingMap.containsValue(event.getInventory()))
            openingMap.remove(event.getPlayer());
    }

    @EventHandler
    public void onGuiOpen(InventoryOpenEvent event) {
        try {
            if (event.getInventory().equals(openingMap.get(event.getPlayer()))) {
                if (!event.getPlayer().hasPermission("lss233.recipe.gui")) {
                    event.getPlayer().closeInventory();
                    return;
                }
                Set<String> list = Storage.getRecipeList();
                for (int i = 0; i < list.size(); i++) {
                    event.getInventory().setItem(i, Storage.getRecipe(list.iterator().next()).getResultItem());
                }

            }
        } catch (Exception e) {
            RecipeGuide.sendThrowable(event.getPlayer(), e);
        }
    }

    @EventHandler(priority = EventPriority.LOWEST)
    public void onGuiClick(InventoryClickEvent event) {
        try {
            if (openingMap.get(event.getWhoClicked()) == null) return;
            if (event.getClickedInventory().equals(openingMap.get(event.getWhoClicked()))) {
                if (event.getCurrentItem() == null) return;
                if (event.getWhoClicked().hasPermission("lss233.recipe.gui")) {
                    event.setCancelled(true);
                    Inventory inventory = Bukkit.getServer().createInventory(null, frame.length, "  ===-= Guide.");
                    Set<String> list = Storage.getRecipeList();
                    for (int i = 0; i < list.size(); i++) {
                        RecipeData recipe = Storage.getRecipe(list.iterator().next());
                        if (mayEquals(recipe.getResultItem(), event.getCurrentItem())) {
                            event.getWhoClicked().closeInventory();
                            openingMap.remove(event.getWhoClicked());
                            int itemPos = 0;
                            for (int k = 0; k < frame.length; k++) {
                                ItemStack item = null;
                                ItemMeta meta = null;
                                switch (frame[k]) {
                                    case 0:
                                        item = new ItemStack(Material.STAINED_GLASS_PANE);
                                        meta = item.getItemMeta();
                                        meta.setDisplayName(ChatColor.GRAY + "=X=");
                                        break;
                                    case 1:
                                        item = recipe.getRecipeItems().get(itemPos) == null ? new ItemStack(Material.AIR) : recipe.getRecipeItems().get(itemPos);
                                        meta = item.getItemMeta();
                                        itemPos++;
                                        break;
                                    case 4:
                                        item = recipe.getResultItem();
                                        meta = item.getItemMeta();
                                        break;
                                }
                                item.setItemMeta(meta);
                                inventory.setItem(k, item);
                            }
                            openingMap.put((Player) event.getWhoClicked(),inventory);
                            event.getWhoClicked().openInventory(inventory);
                            break;
                        }
                    }
                }
            }
        } catch (Exception e) {
            RecipeGuide.sendThrowable(event.getWhoClicked(), e);
        }
    }

    private boolean mayEquals(ItemStack resultItem, ItemStack currentItem) {
        if (!resultItem.getType().equals(currentItem.getType()))
            return false;
        if (resultItem.getAmount() != currentItem.getAmount())
            return false;
        if (resultItem.hasItemMeta() && currentItem.hasItemMeta()) {
            if (resultItem.getItemMeta().getDisplayName() != null && currentItem.getItemMeta().getDisplayName() != null) {
                if (!resultItem.getItemMeta().getDisplayName().equals(currentItem.getItemMeta().getDisplayName()))
                    return false;
            }
            if (resultItem.getItemMeta().getLore() != null && currentItem.getItemMeta().getLore() != null) {
                if (!resultItem.getItemMeta().getLore().equals(currentItem.getItemMeta().getLore()))
                    return false;
            }
        }
        return true;
    }
}
